做完文章的系統,以及自動化測試之後,我們要開始允許用戶撰寫文章了。
在[Day 22] 實作用戶權限!談 Laravel Policy 這篇文章裡面,我們提到了如何用 Laravel Policy 來協助我們管理文章編輯的權限。
其實,Laravel 還提供另一種管理權限的方式,而且比起 Laravel Policy 要更簡單!這個做法就是標題所說的 Laravel Gate
今天我們就來學看看怎麼使用 Laravel Gate
根據官方的說明
Laravel provides two primary ways of authorizing actions: gates and policies. Think of gates and policies like routes and controllers. Gates provide a simple, closure-based approach to authorization while policies, like controllers, group logic around a particular model or resource.
簡單的說,比起功能比較完整的 Laravel Policy,Laravel Gate 可以提供比較容易撰寫,但是功能相對單純的權限管理。
要撰寫 gate,我們要先定義在 App\Providers\AuthServiceProvider  裡面的 boot() 裡面:
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
 
/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();
 
    Gate::define('update-post', function (User $user, Post $post) {
        return $user->id === $post->user_id;
    });
}
當然,如果你想沿用已經撰寫好的 Policy,也是可以的
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
 
/**
 * Register any authentication / authorization services.
 *
 * @return void
 */
public function boot()
{
    $this->registerPolicies();
 
    Gate::define('update-post', [PostPolicy::class, 'update']);
}
定義好了之後,我們就可以任意地在 controller 內使用這個 gate
if (! Gate::allows('update-post', $post)) {
	abort(403);
}
就這樣!是不是很簡單呢?
你也可以宣告一個會回傳特定回應的 gate
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
    return $user->isAdmin
                ? Response::allow()
                : Response::deny('You must be an administrator.');
});
這樣就可以客製化自己希望的回傳內容了。
除了客製化內容,你也可以客製化回傳的 HTTP action
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
 
Gate::define('edit-settings', function (User $user) {
    return $user->isAdmin
                ? Response::allow()
                : Response::denyWithStatus(418);// I am a teapot
});
如果你只是想回傳單純的 404,還可以寫得更加語意化
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
 
Gate::define('edit-settings', function (User $user) {
    return $user->isAdmin
                ? Response::allow()
                : Response::denyAsNotFound();
});
在某些狀況,你可能會覺得註冊 gate 還是太麻煩了,希望可以有更簡單的用法,Laravel 還可以這樣寫
use Illuminate\Support\Facades\Gate;
 
Gate::allowIf(fn ($user) => $user->isAdministrator());
這樣一來,如果用戶不是 Administrator 的話,Laravel 就會自動拋出 AuthorizationException,變成回傳的時候就會自動變成 403 Forbidden 了!是不是很方便呢?
今天有關權限的分享就到這邊。各位明天見!